#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dos.h>
#include <unistd.h>
#define HEADER1 " -------------------------------BOOK TICKET----------------------------------\n"
#define HEADER2 " |  number  |start city|reach city|takeofftime|receivetime|price|ticketnumber|\n"
#define HEADER3 " |----------|----------|----------|-----------|-----------|-----|------------|\n"
#define FORMAT  " |%-10s|%-10s|%-10s|%-10s |%-10s |%5d|  %5d     |\n"
#define DATA p->data.num,p->data.start_city,p->data.reach_city,p->data.takeoff_time,p->data.receive_time,p->data.price,p->data.ticket_num
int saveflag = 0;

/*火车信息的结构体*/
struct train
{
    char num[10];           // 列车号
    char start_city[10];    // 出发城市
    char reach_city[10];    // 目标城市
    char takeoff_time[10];  // 发车时间
    char receive_time[10];  // 到达时间
    int price;              // 票价
    int ticket_num;         //票数
};
/*订票人信息*/
struct man
{
    char num[10];           // ID
    char name[10];          // 姓名
    int bookNum;            // 订票数
};
/*火车信息A 链表*/
typedef struct node
{
    struct train data;
    struct node * next;
}Node, *Link;
/*订票人链表*/
typedef struct Man
{
    struct man data;
    struct Man * next;
}book, *bookLink;
/*初始界面*/
void menu()
{
    puts("\n\n");
    puts("\t\t|------------------------------------------------------|");
    puts("\t\t|                   Booking Tickets                    |");
    puts("\t\t|------------------------------------------------------|");
    puts("\t\t|       0:退出系统                                      |");
    puts("\t\t|       1:插入一个火车信息                                |");
    puts("\t\t|       2:查找一个火车信息                                |");
    puts("\t\t|       3:订票                                          |");
    puts("\t\t|       4:修改火车信息                                   |");
    puts("\t\t|       5:显示火车信息                                   |");
    puts("\t\t|       6:保存火车信息至文件                              |");
    puts("\t\t|------------------------------------------------------|");
}
/*添加一个火车信息*/
void Train_info(Link linkhead)
{
    // tail 是尾指针，s是工作指针，p是分配新节点的指针
    struct node *p, *tail, *s;
    char num[10];
    tail = linkhead;
    s = linkhead->next;
    while(tail->next != NULL)
        tail = tail->next;              // 找到尾指针
    while(1)
    {
        printf("请输入车号(0-return)");
        scanf("%s", num);
        if (strcmp(num, "0") == 0)
            break;                      // 意思是不再添加新火车线路节点
        // 判断这个条火车线路是否已经存在
        while(s)
        {
            if(strcmp(s->data.num, num) == 0)
            {
                printf("这条'%s'火车线路已经存在了!\n", num);
                return ;
            }
            s = s->next;
        }
    }
    p = (struct node*)malloc(sizeof(struct node));
    strcpy(p->data.num, num);               // 设置车号
    printf("输入起始城市：");
    scanf("%s", p->data.start_city);        // 输入出发城市
    printf("输入到站城市：");
    scanf("%s", p->data.reach_city);       // 输入到站城市
    printf("输入出发时间：");
    scanf("%s", p->data.takeoff_time);     // 输入出发时间
    printf("输入到站时间：");
    scanf("%s", p->data.receive_time);     // 输入到站时间
    printf("输入火车票价：");
    scanf("%s", p->data.price);            // 输入火车票价
    printf("输入预定票数：");
    scanf("%s", p->data.ticket_num);       // 输入预定票数
    
    // 更新尾指针，我们是尾插法，新指针是尾指针
    p->next = NULL;
    tail->next = p;
    tail = p;
    saveflag = 1;                          // 保存标志
}
/* 打印火车票信息 */
void print_header()
{
    // 格式化输出表头
    printf(HEADER1);
    printf(HEADER2);
    printf(HEADER3);
}
void print_data(Node * q)
{
    // 格式化输出表中数据
    Node * p;
    p = q;
    printf(FORMAT, DATA);
}
/* 查询火车信息 */
void search_train(Link l)
{
    Node * s[10], * r;
    int sel, k, i = 0;
    char str1[5], str2[10];
    if (!l->next)
    {
        printf("这里没有任何记录信息！");
        return;
    }
    printf("请选择：\n\
            1: 根据车号查询；\n\
            2: 根据城市查询；\n");
    scanf("%d", &sel);          // 输入选择的序号
    if (sel == 1)
    {
        printf("请输入车号：");
        scanf("%s", str1);
        r = l->next;
        while (r != NULL)
        {
            // 检测已有车号有没有和输入的车号匹配的
            if (strcmp(r->data.num, str1) == 0)
            {
                s[i] = r;
                i++;
                break;
            }
            else
                r = r->next;
        }
    }
    else if (sel == 2)
    {
        printf("输入线路中到达的城市：");
        scanf("%s", str2);
        r = l->next;
        // 循环遍历寻找是否有鱼与输入城市相匹配的火车线路
        while (r != NULL)
        {
            if (strcmp(r->data.reach_city, str2) == 0)
            {
                s[i] = r;
                i++;
                r = r->next;
            }
            else
                r = r->next;
        }
        if (i == 0)
            printf("找不到！");
        else
        {
            print_header();
            for (k=0; k<i; k++)
                print_data(s[k]);
        }
    }
}
/* 订票子模块 */
void Book_ticket(Link l, bookLink k)
{
    Node *r[10], *p;
    char ch[2], tnum[10], str[10], name_g[10], id_g[10];
    book *q, *h;
    int i = 0, t = 0, flag = 0, dnum;
    q = k;
    // 设置尾指针
    while (q->next != NULL)
        q = q->next;
    printf("输入你想去的城市：");
    // ------------------差异点！注意！以后来调试！去掉了 &--------------------
    scanf("%s", str);
    p = l->next;
    while (p != NULL)
    {
        // 所有 到达城市
        if (strcmp(p->data.reach_city, str) == 0)
        {
            r[i] = p;
            i++;
        }
        p = p->next;
    }
    printf("\n我们检测出了有 %d 条终点站符合条件的线路\n", i);
    print_header();
    // 输出所有符合的线路信息
    for (t=0; t<i; t++)
        print_data(r[t]);
    if (i == 0)
        printf("\n 抱歉！我们找不到符合的线路！\n");
    else
    {
        printf("\n您想要订这条线路的票吗?\n<y/n>\n");
        scanf("%s", ch);
        // 确认订票
        if (strcmp(ch, "Y") == 0 || strcmp(ch, "y") == 0)
        {
            h = (book*)malloc(sizeof(book));
            printf("输入您的名字: ");
            scanf("%s", name_g);
            strcpy(h->data.name, name_g);
            printf("输入您的ID: ");
            scanf("%s", id_g);
            strcpy(h->data.num, id_g);
            printf("请输入您的车号: ");
            scanf("%s", tnum);
            for (t=0; t<i; t++)
            {
                // 循环找到符合车号ID的火车线路
                if (strcmp(r[t]->data.num, tnum) == 0)
                {
                    // 没票了
                    if (r[t]->data.ticket_num < 1)
                    {
                        printf("抱歉！没票了！");
                        sleep(2);
                        return;
                    }
                    printf("还剩 %d 张票\n", r[t]->data.ticket_num);
                    flag = 1;
                    break;
                }
            }
            if (flag == 0)
            {
                printf("输入错误!!!");
                sleep(2);
                return;
            }
            printf("输入您订的票数:");
            scanf("%d", &dnum);
            // 订票成功则相应可订票数减少
            r[t]->data.ticket_num = r[t]->data.ticket_num - dnum;
            // 补充 h指针 信息，转换尾指针
            h->data.bookNum = dnum;
            h->next = NULL;
            q->next = h;
            q = h;

            printf("\n真幸运,正好有票,您已经成功订票！");
            // 等待用户按任意键后返回主选择界面
            getch();
            saveflag = 1;
        }
    }
}

/* 修改火车信息 */
void Modify(Link l)
{
    Node * p;
    char tnum[10], ch;
    p = l->next;
    if (!p)
    {
        printf("\n这里没有记录可以修改!\n");
        return;
    }
    else
    {
        printf("\n你想要修改火车信息吗?(y/n)\n");
        getchar();
        scanf("%c", &ch);
        if (ch == 'y' || ch == 'Y')
        {
            printf("\n输入车号:\n");
            scanf("%s", tnum);
            // 循环找到符合条件的车号
            while (p != NULL)
            {
                if (strcmp(p->data.num, tnum) == 0)
                    break;
                else
                    p = p->next;
            }
            if (p)
            {
                printf("输入新的车号：");
                scanf("%s", &p->data.num);
                printf("输入新的起始站：");
                scanf("%s", &p->data.start_city);
                printf("输入新的终点站：");
                scanf("%s", &p->data.reach_city);
                printf("输入新的发车时间：");
                scanf("%s", &p->data.takeoff_time);
                printf("输入新的到达时间：");
                scanf("%s", &p->data.receive_time);
                printf("输入新的车票价格：");
                scanf("%d", &p->data.price);
                printf("输入新的可订票数：");
                scanf("%s", &p->data.ticket_num);
                
                printf("\n修改火车信息已经成功!");
                saveflag = 1;
            }
            else
                printf("\t找不到该火车信息!\t");            
        }
    }
}

/* 自定义函数显示列车信息 */
void show_train(Link l)
{
    Node * p;
    p = l->next;
    print_header();
    if (l->next == NULL)
        printf("没有火车记录了");
    else
    {
        while (p != NULL)
        {
            print_data(p);
            p = p->next;
        }
    }
}
/* 保存火车信息 */
void Save_Train_Info(Link l)
{
    FILE * fp;
    Node * p;
    int count=0, flag=1;
    fp = fopen("./tarin.txt", 'wb');
    if (fp == NULL)
    {
        printf("文件打开失败！");
        return;
    }
    p = l->next;
    while(p)
    {
        // 将链表节点 p 的数据以二进制形式写入文件，并验证写入操作是否成功
        if (fwrite(p, sizeof(Node), 1, fp) == 1)
        {
            p = p->next;
            count++;
        }
        else
        {
            flag = 0;
            break;
        }
    }
    if (flag)
    {
        printf("保存了 %d 订票记录", count);
        saveflag = 0;
    }
    fclose(fp);
}

void Save_Book_Info(bookLink k)
{
    FILE * fp;
    book * p;
    int count=0, flag=1;
    fp = fopen("", "wb");
    if (fp == NULL)
    {
        printf("文件打开失败!");
        return;
    }
    p = k->next;
    while(p)
    {
        if (fwrite(p, sizeof(book), 1, fp) == 1)
        {
            p = p->next;
            count++;
        }
        else
        {
            flag = 0;
            break;
        }
    }
    if (flag)
    {
        printf("已保存 %d 订票记录\n", count);
        saveflag = 0;
    }
    fclose(fp);
}
main_1()
{
    FILE *fp1, *fp2;
    Node *p, *tail_1;
    char ch1, ch2;
    Link l;
    bookLink k;
    book *t, *tail_2;
    int sel;
    // 初始化尾节点
    l = (Node*)malloc(sizeof(Node));
    l->next = NULL;
    tail_1 = l;
    k = (book*)malloc(sizeof(book));
    k->next = NULL;
    tail_2 = k;
    // 打开储存车票信息的文件
    fp1 = open("", "ab+");
    if (fp1 == NULL)
    {
        printf("无法打开文件！");
        return 0;
    }
    // 循环直到文章末尾
    while (!feof(fp1))
    {
        p = (Node*)malloc(sizeof(Node));
        if (fread(p, sizeof(Node), 1, fp1) == 1)
        {
            // 尾插法
            p->next = NULL;
            tail_1->next = p;
            tail_1 = p;
        }
    }
    
    // 打开储存订票人信息的文件
    fp2 = open("", "ab+");
    if (fp2 == NULL)
    {
        printf("无法打开文件！");
        return 0;
    }
    // 循环直到文章末尾
    while (!feof(fp2))
    {
        t = (book*)malloc(sizeof(book));
        if (fread(t, sizeof(Node), 1, fp2) == 1)
        {
            // 尾插法
            t->next = NULL;
            tail_2->next = t;
            tail_2 = t;
        }
    }
    fclose(fp2);
    
    while (1)
    {
        system("CLS");
        menu();
        printf("\t请选择:(0-6)");
        scanf("%d", &sel);
        system("CLS");
        if (sel == 0)
        {
            // 退出时判断信息是否保存
            if (saveflag == 1)
            {
                getchar();
                printf("文件已被更改！你想要保存它吗？(y/n)\n");
                scanf("%c", &ch1);
                if (ch1 == 'y' || ch1 == "Y")
                {
                    Save_Book_Info(k);
                    Save_Train_Info(l);
                }
            }
            printf("\n谢谢你捏!\n");
            break;
        }
        // 对 sel 的不同输入做出选择
        switch (sel)
        {
            case 1:
                // 添加火车信息
                Train_info(l);
                break;
            case 2:
                // 查找火车信息
                search_train(l);
                break;
            case 3:
                // 订车票
                Book_ticket(l, k);
            case 4:
                // 修改火车信息
                Modify(l);
                break;
            case 5:
                // 显示火车信息
                show_train(l);
                break;
            case 6:
                // 保存信息到文件
                Save_Train_Info(l);
                Save_Book_Info(k);
                break;
            case 0:
                return 0;
        }
        printf("\n请按任何键以继续————");
        getch();
    }
}